
package org.apache.solr.util;

import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import java.util.TimeZone;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * Simple utilities for working with TimeZones
 * @see java.util.TimeZone
 */
public final class TimeZoneUtils {

    private static Pattern CUSTOM_ID_REGEX = Pattern.compile("GMT(?:\\+|\\-)(\\d{1,2})(?::?(\\d{2}))?");

    private TimeZoneUtils() {
    }
    /**
     * An immutable Set of all TimeZone IDs supported by the TimeZone class at
     * the moment the TimeZoneUtils was initialized.
     *
     * @see TimeZone#getAvailableIDs
     */
    public static final Set<String> KNOWN_TIMEZONE_IDS = Collections.unmodifiableSet(new HashSet<>(Arrays.asList(TimeZone.getAvailableIDs())));

    /**
     * This method is provided as a replacement for TimeZone.getTimeZone but
     * without the annoying behavior of returning "GMT" for gibberish input. <p>
     * This method will return null unless the input is either: </p> <ul>
     * <li>Included in the set of known TimeZone IDs</li> <li>A "CustomID"
     * specified as a numeric offset from "GMT"</li> </ul>
     *
     * @param ID Either a TimeZone ID found in KNOWN_TIMEZONE_IDS, or a
     * "CustomID" specified as a GMT offset.
     * @return A TimeZone object corresponding to the input, or null if no such
     * TimeZone is supported.
     * @see #KNOWN_TIMEZONE_IDS
     * @see TimeZone
     */
    public static TimeZone getTimeZone(final String ID) {

        if (null == ID) {
            return null;
        }
        if (KNOWN_TIMEZONE_IDS.contains(ID)) {
            return TimeZone.getTimeZone(ID);
        }

        Matcher matcher = CUSTOM_ID_REGEX.matcher(ID);
        if (matcher.matches()) {
            int hour = Integer.parseInt(matcher.group(1));
            if (hour < 0 || 23 < hour) {
                return null;
            }

            final String minStr = matcher.group(2);
            if (null != minStr) {
                int min = Integer.parseInt(minStr);
                if (min < 0 || 59 < min) {
                    return null;
                }
            }
            return TimeZone.getTimeZone(ID);
        }
        return null;
    }
}
